package cn.leaf.calculator;

import cn.leaf.calculator.bean.CalUnitEntity;
import cn.leaf.calculator.bean.FormulationCalUnitEntity;
import cn.leaf.calculator.datasource.CalDataSources;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.convert.converter.Converter;
import org.springframework.util.Assert;

import java.util.List;

/**
 * formula cal helper
 *
 * @author 李克国
 * @version 1.0.0
 */
@Slf4j
public abstract class AbstractFormulaCalHelper<T> implements FormulaCalHelper<T> {

    private CalDataSources<T> dataSources;

    private Converter<T, ? extends FormulationCalUnitEntity<T>> converter;

    @Override
    public void bind(CalDataSources<T> dataSources) {
        this.dataSources = dataSources;
    }

    @Override
    public void start() {
        Assert.notNull(dataSources, "CalHelperStartException:未绑定数据源");
        if (converter != null) {
            dataSources.setConverter(converter);
        }
        dataSources.initialize();
        log.info("公式计算助手：计算数据源初始化：完成");
        log.info("公式计算助手：计算：开始");
        while (dataSources.hasNext()) {
            execute(dataSources.next());
        }
        log.info("公式计算助手：计算：完成");
    }

    @Override
    public List<T> getResults() {
        return dataSources.getCalResult();
    }

    @Override
    public void setConverter(Converter<T, FormulationCalUnitEntity<T>> converter) {
        this.converter = converter;
    }

    public void execute(FormulationCalUnitEntity<T> calUnitEntity) {
        if (CalUnitEntity.CAL_INIT_ED == calUnitEntity.getState()) {
            // 如果不需要等待，直接计算
            calUnitEntity.updateState(cal(calUnitEntity) ? CalUnitEntity.CAL_OVER : CalUnitEntity.CAL_FAIL);
        } else if (CalUnitEntity.CAL_WAIT == calUnitEntity.getState()) {
            // 如果需要等待，递归计算
            calUnitEntity.getParamEntityList().forEach(e -> {
                if (e instanceof FormulationCalUnitEntity) {
                    execute((FormulationCalUnitEntity<T>) e);
                }
            });
            calUnitEntity.updateState(cal(calUnitEntity) ? CalUnitEntity.CAL_OVER : CalUnitEntity.CAL_FAIL);
        }
    }

}
